package org.convallaria.infrastruct.rg.feign;

import feign.Logger;
import feign.Request;
import feign.Retryer;
import feign.codec.ErrorDecoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.TimeUnit;

/**
 * Feign客户端配置
 * 配置Feign的日志、重试、超时等参数
 * 
 * @author gjh
 * @since 2025-01-27
 */
@Slf4j
@Configuration
@EnableFeignClients
public class FeignConfig {
    
    /**
     * Feign日志级别配置
     * 
     * @return 日志级别
     */
    @Bean
    public Logger.Level feignLoggerLevel() {
        return Logger.Level.BASIC;
    }
    
    /**
     * Feign请求配置
     * 
     * @return 请求配置
     */
    @Bean
    public Request.Options feignRequestOptions() {
        return new Request.Options(
                10, TimeUnit.SECONDS,  // 连接超时
                60, TimeUnit.SECONDS,  // 读取超时
                true                   // 跟随重定向
        );
    }
    
    /**
     * Feign重试配置
     * 
     * @return 重试配置
     */
    @Bean
    public Retryer feignRetryer() {
        return new Retryer.Default(
                100,                  // 初始间隔
                1000,                 // 最大间隔
                3                     // 最大重试次数
        );
    }
    
    /**
     * Feign错误解码器
     * 
     * @return 错误解码器
     */
    @Bean
    public ErrorDecoder feignErrorDecoder() {
        return new CustomErrorDecoder();
    }
    
    /**
     * 自定义错误解码器
     */
    public static class CustomErrorDecoder implements ErrorDecoder {
        
        private final ErrorDecoder defaultErrorDecoder = new Default();
        
        @Override
        public Exception decode(String methodKey, feign.Response response) {
            log.error("Feign调用失败: {} - {}", methodKey, response.status());
            
            // 根据HTTP状态码返回不同的异常
            switch (response.status()) {
                case 400:
                    return new IllegalArgumentException("请求参数错误");
                case 401:
                    return new SecurityException("未授权访问");
                case 403:
                    return new SecurityException("禁止访问");
                case 404:
                    return new RuntimeException("服务不存在");
                case 500:
                    return new RuntimeException("服务器内部错误");
                case 502:
                case 503:
                case 504:
                    return new RuntimeException("服务不可用");
                default:
                    return defaultErrorDecoder.decode(methodKey, response);
            }
        }
    }
}
